package com.nuoniu.sibanyun.service.erp.in.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nuoniu.sibanyun.common.constant.RedisConstant;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.common.result.HttpResult;
import com.nuoniu.sibanyun.entity.bo.UsedGradeRuleBo;
import com.nuoniu.sibanyun.entity.erp.in.InWarehouse;
import com.nuoniu.sibanyun.mapper.erp.in.InWarehouseMapper;
import com.nuoniu.sibanyun.service.crm.ICrmGoodsService;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpGradeRuleService;
import com.nuoniu.sibanyun.service.erp.in.IInInventoryLocationService;
import com.nuoniu.sibanyun.service.erp.in.IInWarehouseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.service.redis.RedisService;
import com.nuoniu.sibanyun.userThread.DataScope;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 仓库管理 服务实现类
 * </p>
 *
 * @author baiqiang
 * @since 2020-09-22
 */
@Log4j2
@Service
public class InWarehouseServiceImpl extends ServiceImpl<InWarehouseMapper, InWarehouse> implements IInWarehouseService {


    @Autowired
    private IErpAccountService erpAccountService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private IInInventoryLocationService locationService;
    @Autowired
    private IErpGradeRuleService erpGradeRuleService;
    @Autowired
    private ICrmGoodsService goodsService;

    @Override
    public Page<InWarehouse> pageList(Page pages, InWarehouse inWarehouse) {
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<InWarehouse> queryWrapper = new QueryWrapper<>(inWarehouse);
        queryWrapper.eq("company_id", userInfo.getCompanyId());
        queryWrapper.eq("account_id", inWarehouse.getAccountId());
        if(inWarehouse.getStorageBin() != null) {
            queryWrapper.eq("storage_bin", inWarehouse.getStorageBin());
        }
        if(StringUtils.isNotBlank(inWarehouse.getWhCode())) {
            queryWrapper.eq("wh_code", inWarehouse.getWhCode());
        }
        if(StringUtils.isNotBlank(inWarehouse.getWhName())) {
            queryWrapper.like("wh_name", inWarehouse.getWhName());
        }
        queryWrapper.orderByAsc("wh_code");
        Page page = page(pages, queryWrapper);
        return page;
    }

    @Override
    public void saveInWarehouse(InWarehouse inWarehouse) {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        Set<String> clearUserIds = new HashSet<>();
        if(StringUtils.isBlank(inWarehouse.getWhName())) {
            throw new NuoNiuException("仓库名称不能为空");
        }
        if(StringUtils.isBlank(inWarehouse.getWhCode())) {
            throw new NuoNiuException("仓库编码不能为空");
        }
        if(StringUtils.isBlank(inWarehouse.getWhKeeper())) {
            throw new NuoNiuException("请选择库管员");
        }
        //判断仓库编码规则
        UsedGradeRuleBo usedGradeRuleBo = erpGradeRuleService.checkCode(inWarehouse.getWhCode(), null, null, "warehouse");
        inWarehouse.setGradeRuleLevel(usedGradeRuleBo.getGradeRuleLevel());
        inWarehouse.setGradeRuleStr(usedGradeRuleBo.getGradeRuleStr());
        UserInfo userInfo = UserThreadLocal.get();
        inWarehouse.setCompanyId(userInfo.getCompanyId());
        InWarehouse warehouse = this.getByCode(inWarehouse);
        InWarehouse warehouseByName = this.getByName(inWarehouse);

        if(inWarehouse.getId() != null) {
            InWarehouse oldInWarehouse = getById(inWarehouse.getId());
            inWarehouse.setWhCode(null);
            inWarehouse.setStorageBin(null);
            if(warehouse != null && !warehouse.getId().equals(inWarehouse.getId())) {
                throw new NuoNiuException("编码已存在");
            }
            if(warehouseByName != null && !(warehouseByName.getId().equals(inWarehouse.getId()))) {
                throw new NuoNiuException("名称已存在");
            }

            inWarehouse.setUpdateUserId(userInfo.getUserId());
            /**************  *******************/
            locationService.updateWarehouse(inWarehouse);
            //1.获取 更新后的 库管员IDs
            String whKeeperStr = inWarehouse.getWhKeeper();
            String[] whKeeperArr = whKeeperStr.split(",");
            List<String> whKeeperList = Arrays.asList(whKeeperArr);
            clearUserIds.addAll(whKeeperList);
            //2.获取 更新前的 库管员IDs
            String oldInWarehouseStr = oldInWarehouse.getWhKeeper();
            if (StringUtils.isNotBlank(oldInWarehouseStr)){
                String[] oldInWarehouseArr = oldInWarehouseStr.split(",");
                List<String> oldInWarehouseList = Arrays.asList(oldInWarehouseArr);
                clearUserIds.addAll(oldInWarehouseList);
            }
            //inventoryService.updateWarehouse(inWarehouse);
        }else {
            if(warehouse != null) {
                throw new NuoNiuException("编码已存在");
            }
            if(warehouseByName != null) {
                throw new NuoNiuException("名称已存在");
            }

            String whKeeperStr = inWarehouse.getWhKeeper();
            String[] whKeeperArr = whKeeperStr.split(",");
            List<String> whKeeperList = Arrays.asList(whKeeperArr);
            clearUserIds.addAll(whKeeperList);

            inWarehouse.setAccountId(currentAccountId);
            inWarehouse.setCreateUserId(userInfo.getUserId());
            inWarehouse.setCreateUserName(userInfo.getRealName());
        }
        this.saveOrUpdate(inWarehouse);
        //清除 缓存操作
        if(clearUserIds.size() > 0){
            clearMyWarehouseIdsRedis(clearUserIds);
        }
    }

    @Override
    public InWarehouse getByCode(InWarehouse inWarehouse) {
        return baseMapper.getByCode(inWarehouse);
    }

    @Override
    public InWarehouse getByName(InWarehouse inWarehouse) {
        return baseMapper.getByName(inWarehouse);
    }

    @Override
    public List<Long> myWarehouseIds() {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        List<Long> result = null;
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        Integer officeId = userInfo.getOfficeId();
        Integer userId = userInfo.getUserId();
        //1.解析 数据权限
        DataScope dataScope = userInfo.getDataScope();
        Integer type = dataScope.getType();
        String officeIdsStr = dataScope.getOfficeIds();
        String userIds = dataScope.getUserIds();
        String key = RedisConstant.scb_warehouse_IDS + userId;
        Object inWarehouseIdsObj = redisService.get(key);
        log.debug("获取Key:{}的仓库权限ID:{}",key,inWarehouseIdsObj);
        if(null != inWarehouseIdsObj){
            return (List<Long>)inWarehouseIdsObj;
        }
        else{
            switch (type){
                //1:个人权限
                case 1: result = baseMapper.listPersonalInWarehouseIds(userId,currentAccountId,companyId);break;
                //2:部门权限
                case 2: result = baseMapper.listOfficeInWarehouseIds(officeId,currentAccountId,companyId);break;
                //3.公司权限
                case 3: result = baseMapper.listCompanyInWarehouseIds(currentAccountId,companyId);break;
                //4.跨部门
                case 4: result = baseMapper.listOtherOfficesInWarehouseIds(officeIdsStr,userId,currentAccountId,companyId);break;
                //5:自定义人员
                case 5: result = baseMapper.listOtherUsersInWarehouseIds(userIds,userId,currentAccountId,companyId);break;
                //6. 跨部门 + 自定义人员
                case 6: result = baseMapper.listOtherOfficesAndOtherUsersInWarehouseIds(officeIdsStr,userIds,userId,currentAccountId,companyId);break;
            }
            if(null != result && result.size() > 0)redisService.set(key,result);
        }

        return result;
    }

    @Override
    public void clearMyWarehouseIdsRedis(Set<String> userIds) {
        userIds.forEach(userId-> redisService.del(RedisConstant.scb_warehouse_IDS + userId));
    }

    @Override
    public boolean isHaveOperationRight(Long inWarehouseId) {
        Integer companySysRoleIdByCompanyId = goodsService.getCompanySysRoleIdByCompanyId();
        UserInfo userInfo = UserThreadLocal.get();
        //如果是租户管理员，可直接赋予权限
        if (userInfo.getRoleIds().contains(companySysRoleIdByCompanyId)){
            return true;
        }
        List<InWarehouse> inWarehouses = listMyOperationInWarehouses(null);
        boolean match = inWarehouses.stream().anyMatch(f -> f.getId().equals(inWarehouseId));
        return match;
    }

    @Override
    public boolean isHaveInInventoryLocation(Long inWarehouseId) {
        boolean haveInInventoryLocation = baseMapper.isHaveInInventoryLocation(inWarehouseId);
        return haveInInventoryLocation;
    }

    @Override
    public List<InWarehouse> listMyOperationInWarehouses(String keyWord) {
        Integer companySysRoleIdByCompanyId = goodsService.getCompanySysRoleIdByCompanyId();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        Integer userId = userInfo.getUserId();
        if (userInfo.getRoleIds().contains(companySysRoleIdByCompanyId)){
            return listCompanyInWarehouses(keyWord);
        }
//        Object myInWarehouseObj = redisService.get(RedisConstant.MY_scb_warehouseS + userId);
        List<InWarehouse> inWarehouses = baseMapper.listPersonalInWarehouses(userId, currentAccountId, companyId,keyWord);
        return inWarehouses;
    }

    @Override
    public List<InWarehouse> listCompanyInWarehouses(String keyWord) {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        UserInfo userInfo = UserThreadLocal.get();
        Integer companyId = userInfo.getCompanyId();
        List<InWarehouse> inWarehouses = baseMapper.listCompanyInWarehouses( currentAccountId, companyId,keyWord);
        return inWarehouses;
    }

    @Override
    public List<String> getKeepers(List<Integer> ids) {
        QueryWrapper<InWarehouse> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("wh_keeper");
        queryWrapper.in("id",ids);
        List<InWarehouse> list = list(queryWrapper);
        List<String> keeperList = list.stream().map(f -> f.getWhKeeper()).collect(Collectors.toList());
        return keeperList;
    }


}
